/*
 * UAE - The Un*x Amiga Emulator
 *
 * Emulates simple protection dongles
 *
 * Copyright 2009 Toni Wilen
 */

#include "sysconfig.h"
#include "uae.h"
#include "events.h"

#define ROBOCOP3 1
#define LEADERBOARD 2
#define BAT2 3
#define ITALY90 4
#define DAMESGRANDMAITRE 5
#define RUGBYCOACH 6
#define CRICKETCAPTAIN 7
#define LEVIATHAN 8
#define LOGISTIX 10

static int flag;
static uint cycles;

/*
   Robocop 3
   - set firebutton as output
   - read JOY1DAT
   - pulse firebutton (high->low)
   - read JOY1DAT
   - JOY1DAT bit 8 must toggle

   Leaderboard
   - JOY1DAT, both up and down active (0x0101)

   B.A.T. II
   - set all serial pins as output except CTS
   - game pulses DTR (high->low)
   - CTS must be one
   - delay
   - CTS must be zero

   Italy'90 Soccer
   - 220k resistor between pins 5 (+5v) and 7 (POTX)
   - POT1DAT POTX must be between 0x32 and 0x60

   Dames Grand Maitre
   - read POT1
   - POT1X != POT1Y
   - POT1Y * 256 / POT1X must be between 450 and 500

   Rugby Coach
   - JOY1DAT, left, up and down active (0x0301)

   Cricket Captain
   - JOY0DAT bits 0 and 1:
   - 10 01 11 allowed
   - must continuously change state

   Leviathan
   - same as Leaderboard but in mouse port

   Logistix/SuperBase
   - second button must be high
   - POT1X = 150k
   - POT1Y = 100k
   - POT1X * 10 / POT1Y must be between 12 and 33


 */

static byte oldcia[2][16];

void dongle_reset()
{
    flag = 0;
    memset(oldcia, 0, sizeof oldcia);
}

byte dongle_cia_read(int cia, int reg, byte val)
{
    if (!g_curr_conf.dongle)
        return val;
    switch (g_curr_conf.dongle)
    {
        case BAT2:
            if (cia == 1 && reg == 0)
            {
                if (!flag || get_cycles() > cycles + CYCLE_UNIT * 200)
                {
                    val &= ~0x10;
                    flag = 0;
                }
                else
                {
                    val |= 0x10;
                }
            }
            break;
    }
    return val;
}

void dongle_cia_write(int cia, int reg, byte val)
{
    if (!g_curr_conf.dongle)
        return;
    switch (g_curr_conf.dongle)
    {
        case ROBOCOP3:
            if (cia == 0 && reg == 0 && (val & 0x80))
                flag ^= 1;
            break;
        case BAT2:
            if (cia == 1 && reg == 0 && !(val & 0x80))
            {
                flag = 1;
                cycles = get_cycles();
            }
            break;
    }
    oldcia[cia][reg] = val;
}

void dongle_joytest(ushort val)
{
}

ushort dongle_joydat(int port, ushort val)
{
    if (!g_curr_conf.dongle)
        return val;
    switch (g_curr_conf.dongle)
    {
        case ROBOCOP3:
            if (port == 1 && flag)
                val += 0x100;
            break;
        case LEADERBOARD:
            if (port == 1)
            {
                val &= ~0x0303;
                val |= 0x0101;
            }
            break;
        case LEVIATHAN:
            if (port == 0)
            {
                val &= ~0x0303;
                val |= 0x0101;
            }
            break;
        case RUGBYCOACH:
            if (port == 1)
            {
                val &= ~0x0303;
                val |= 0x0301;
            }
            break;
        case CRICKETCAPTAIN:
            if (port == 0)
            {
                val &= ~0x0003;
                if (flag == 0)
                    val |= 0x0001;
                else
                    val |= 0x0002;
            }
            flag ^= 1;
            break;
    }
    return val;
}

void dongle_potgo(ushort val)
{
    if (!g_curr_conf.dongle)
        return;
    switch (g_curr_conf.dongle)
    {
        case ITALY90:
        case LOGISTIX:
        case DAMESGRANDMAITRE:
            flag = (uaerand() & 7) - 3;
            break;
    }
}

ushort dongle_potgor(ushort val)
{
    if (!g_curr_conf.dongle)
        return val;
    switch (g_curr_conf.dongle)
    {
        case LOGISTIX:
            val |= 1 << 14;
            break;
    }
    return val;
}

int dongle_analogjoy(int joy, int axis)
{
    int v = -1;
    if (!g_curr_conf.dongle)
        return -1;
    switch (g_curr_conf.dongle)
    {
        case ITALY90:
            if (joy == 1 && axis == 0)
                v = 73;
            break;
        case LOGISTIX:
            if (joy == 1)
            {
                if (axis == 0)
                    v = 21;
                if (axis == 1)
                    v = 10;
            }
            break;
        case DAMESGRANDMAITRE:
            if (joy == 1)
            {
                if (axis == 1)
                    v = 80;
                if (axis == 0)
                    v = 43;
            }
            break;
    }
    if (v >= 0)
    {
        v += flag;
        if (v < 0)
            v = 0;
    }
    return v;
}